package com.andova.glcamera.glsurface

import android.content.Context
import android.graphics.SurfaceTexture
import android.opengl.GLES11Ext
import android.opengl.GLES30
import android.opengl.GLSurfaceView
import android.util.AttributeSet
import com.andova.image.glesInitialize
import javax.microedition.khronos.egl.EGLConfig
import javax.microedition.khronos.opengles.GL10

open class CameraGLSurfaceView(context: Context, attrs: AttributeSet?) : GLSurfaceView(context, attrs), GLSurfaceView.Renderer, SurfaceTexture.OnFrameAvailableListener {
    init {
        setEGLContextClientVersion(3)
        setRenderer(this)
        renderMode = RENDERMODE_WHEN_DIRTY
    }

    private var texId: Int = -1
    private val transformMatrix = FloatArray(16)
    private var surfaceTexture: SurfaceTexture? = null
    private var provider: Provider? = null
    fun setProvider(provider: Provider) = run { this.provider = provider }
    final override fun onFrameAvailable(surfaceTexture: SurfaceTexture?) = run { requestRender() }
    final override fun onDrawFrame(gl: GL10?) {
        GLES30.glClear(GLES30.GL_COLOR_BUFFER_BIT)
        //更新纹理图像
        surfaceTexture?.updateTexImage()
        surfaceTexture?.getTransformMatrix(transformMatrix)
        provider?.onDrawFrame(texId, transformMatrix)
    }

    final override fun onSurfaceChanged(gl: GL10?, width: Int, height: Int) {
        provider?.onSurfaceChanged(width, height)
    }

    final override fun onSurfaceCreated(gl: GL10?, config: EGLConfig?) {
        GLES30.glClearColor(1f, 1f, 1f, 1f)

        val texIds = IntArray(1)
        GLES30.glGenTextures(1, texIds, 0)
        texId = texIds[0]
        //绑定到外部纹理上
        GLES30.glBindTexture(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, texId)
        //设置纹理过滤参数
        GLES30.glTexParameterf(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, GLES30.GL_TEXTURE_MIN_FILTER, GLES30.GL_NEAREST.toFloat())
        GLES30.glTexParameterf(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, GLES30.GL_TEXTURE_MAG_FILTER, GLES30.GL_LINEAR.toFloat())
        GLES30.glTexParameterf(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, GLES30.GL_TEXTURE_WRAP_S, GLES30.GL_CLAMP_TO_EDGE.toFloat())
        GLES30.glTexParameterf(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, GLES30.GL_TEXTURE_WRAP_T, GLES30.GL_CLAMP_TO_EDGE.toFloat())
        //解除纹理绑定
        GLES30.glBindTexture(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, 0)

        surfaceTexture = SurfaceTexture(texId)
        surfaceTexture?.setOnFrameAvailableListener(this)
        onSurfaceTextureCreated(surfaceTexture)

        val program = provider?.run { glesInitialize(vertexGLSL(context), fragmentGLSL(context)) }
        provider?.onSurfaceCreated(program ?: return)
    }

    open fun onSurfaceTextureCreated(surfaceTexture: SurfaceTexture?) {}

    interface Provider {
        fun vertexGLSL(context: Context): String
        fun fragmentGLSL(context: Context): String
        fun onSurfaceCreated(program: Int)
        fun onSurfaceChanged(width: Int, height: Int)
        fun onDrawFrame(textureId: Int, transformMatrix: FloatArray)
    }
}